<!--聊天信息面板组件-->
<template>
  <div class="mx-auto bg-white rounded-xl shadow-lg overflow-hidden border border-gray-200 h-screen flex flex-col">
    <!-- 聊天头部 -->
    <div class="bg-gradient-to-r from-purple-500 to-purple-700  text-white p-2 pr-4 flex items-center">
      <!-- 用户头像/信息 -->
      <div class="relative mr-4">
        <div class="w-10 h-10 rounded-full overflow-hidden border-2 border-blue-500 ">
          <img :src="chatting.avatarUrl" alt="对方头像" class="w-full h-full object-cover rounded-full">
        </div>
        <div class="absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-purple-100"></div>
      </div>

      <div>
        <span>{{ chatting.showName }}</span>
      </div>
      <div class="ml-auto flex items-center space-x-3">
        <button class="hover:text-gray-200 transition-colors" @click="clickCall(0)">
          <i class="fa fa-phone"></i>
        </button>
        <button class="hover:text-gray-200 transition-colors" @click="clickCall(1)">
          <i class="fa fa-video-camera"></i>
        </button>
        <button class="hover:text-gray-200 transition-colors">
          <i class="fa fa-ellipsis-v"></i>
        </button>
      </div>
    </div>

    <!-- 聊天内容区 -->
    <div ref="messagesBox" id="chat-messages" @scroll="handleScroll"
         class="flex-1 overflow-y-auto py-6 space-y-6 bg-gray-50 pr-2 scrollbar-gutter-keep">
      <!-- 消息列表 -->
      <template v-for="it in chatting.messages">
        <MessageBubble :message="it"/>
      </template>
    </div>

    <!-- 分隔线 -->
    <div class="border-t border-gray-200"></div>

    <!-- 输入区域 -->
    <div class="p-4 flex items-center">
      <!-- 表情包按钮 -->
      <button
          class="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-500 hover:bg-gray-200 transition-colors mr-2"
          @click="clickEmojiPicker"><i class="fa fa-smile"></i>
      </button>
      <!-- 图片按钮 -->
      <label for="upload-image"
             class="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-500 hover:bg-gray-200 transition-colors mr-2 cursor-pointer">
        <i class="fa fa-image"></i>
        <input ref="imageInputEle" id="upload-image" type="file" accept="image/*" class="hidden" @change="clickPicture">
      </label>
      <div class="flex-1 relative">
        <input
            class="w-full pl-4 pr-12 py-3 rounded-full border border-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition-all"
            type="text" v-model="inputMessage"
            placeholder="输入消息..."/>
        <button @click="clickSend"
                class="absolute right-2 top-1/2 -translate-y-1/2 w-8 h-8 rounded-full bg-indigo-500 text-white flex items-center justify-center hover:bg-indigo-600 transition-colors">
          <i class="fa fa-paper-plane text-xs"></i>
        </button>
      </div>
      <button @click="clickVoice"
              class="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-500 hover:bg-gray-200 transition-colors ml-2">
        <i class="fa fa-microphone"></i>
      </button>
    </div>

    <!-- 悬浮图片预览框 -->
    <div
        v-if="previewImage"
        class="fixed bottom-20 left-1/2 -translate-x-1/2 bg-white rounded-lg shadow-md p-2 max-w-[200px] z-50 transition-all duration-300"
        :style="{ transform: `translate(-50%, ${previewImageY}px)` }">
      <!-- 右上角叉号图标 -->
      <button @click="clearPreview"
              class="absolute top-1 right-1 w-5 h-5 flex items-center justify-center rounded-full bg-gray-100 text-gray-500 hover:bg-gray-200 hover:text-gray-700 transition-colors z-10 text-xs">
        <i class="fa fa-times"></i>
      </button>
      <!-- 文件名和大小 -->
      <p class="text-xs font-medium truncate">
        {{ previewImageName }}
        <span class="ml-1 text-gray-500">{{ formatFileSize(previewImageSize) }}</span>
      </p>
      <!-- 预览图容器（固定宽高比 4:3） -->
      <div class="w-full pt-[75%] relative mt-1 rounded overflow-hidden bg-gray-100">
        <img :src="previewImage" alt="预览图片" class="absolute inset-0 w-full h-full  object-cover"/>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {Chatting} from '../../models/chat_model.ts';
import {Msg_Type} from "../../models/message.ts";
import {useChatStore} from "../../stores/chating_store.ts";
import {useContactStore} from "../../stores/contacts_store.ts";
import request from "../../utils/request.js";
import {formatFileSize} from "../../utils/common_function.js"
import UserApi from '../../api/user.js';

import {defineProps, inject, nextTick, onMounted, onUnmounted, ref, watch} from 'vue'
import 'element-plus/es/components/message/style/css';
import 'element-plus/es/components/message-box/style/css';
import 'element-plus/theme-chalk/el-upload.css'
import {ElMessage} from 'element-plus'
import {setOwnerField, showChatMsg} from "@/models/msg_show_process.ts";
import MessageBubble from "@/views/chatting_components/MessageBubble.vue";

//父组件传值时的定义
const props = defineProps<{
  chatting: Chatting;
}>();

const toCall = inject('toCall');

const chatWS = inject('chatWS');

const chatStore = useChatStore();
const contactStore = useContactStore();

// 消息容器引用
const messagesBox = ref(null);
const imageInputEle = ref<HTMLInputElement | null>(null);

const dialogVisible = ref(false);
/**
 * 文字消息相关
 */
//输入的文本框内容
const inputMessage = ref("");
// 预览图片状态
const previewImage = ref('')
const previewImageName = ref('hahaha')
const previewImageSize = ref(0)
const previewImageY = ref(0)

// 移除预览图片
const clearPreview = () => {
  previewImage.value = '';
  previewImageName.value = '';
  previewImageSize.value = 0;
}

const clickCall = (type: number) => {
  const calleeId = props.chatting.isGroup ? props.chatting.relId : props.chatting.peerUserId;
  toCall(type, calleeId, props.chatting.isGroup);
}

/**
 * 检查参数
 * @param content
 * @param receiver
 * @returns {boolean}
 */
const checkArgument = (content: any, receiver: string): boolean => {
  console.debug("receiver = " + receiver)
  if (!receiver) {
    ElMessage.error("发生参数错误");
    console.warn("获取不到 receiver. 无法发生消息")
    return false;
  }

  if (!content || content == "[]") {
    console.warn("发送消息内容不能为空");
    return false;
  }
  return true;
}

/**
 * 发送文本消息
 */
const clickSend = async () => {
  const type = previewImage.value ? Msg_Type.PICTURE : Msg_Type.TEXT;
  let content = inputMessage.value.trim();

  if (previewImage.value) {
    //取第一个图片文件，上传图片
    const firstFile = imageInputEle.value?.files?.[0]
    if (!firstFile) {
      ElMessage.error("未能获取到图片文件，无法发送");
      return;
    }
    const pictureUrl = await uploadFile(firstFile);
    //发送图片：上传图片
    content = "[" + pictureUrl + "]" + inputMessage.value.trim();
  }

  const receiver = getReceiver();
  //发送消息
  if (checkArgument(content, receiver)) {
    sendMessage(content, type, receiver).then(_ => {
      inputMessage.value = "";
      clearPreview();
    })
    scrollToBottom(); // 发送后滚动到底部
  }

}

/* 上传图片相关 */
const uploadFile = async (file: File) => {
  console.log("uploadFile ... ");
  const formData = new FormData();
  formData.append('file', file);

  const resp = await request.post_formData('/file/upload/picture', formData)
  if (resp.ok) {
    let pictureUrl = resp.data.split('?')[0]; //截取一下url
    console.log("uploadFile success.  url=", pictureUrl);
    return pictureUrl;
  } else {
    ElMessage.error("图片文件发送失败. " + resp.msg);
    return "";
  }
}

// 打开表情包选择器（示例函数）
const clickEmojiPicker = () => {
  console.log('打开表情包选择器')
  // 这里可以添加弹出表情包面板的逻辑
}

const clickPicture = (event: any) => {
  const file = event.target.files[0];
  if (!file) return;

  // 赋值文件名和文件大小
  previewImageName.value = file.name;
  previewImageSize.value = file.size;

  // 图片预览（可选）
  const reader = new FileReader();
  reader.onload = (evt) => {

    // 计算预览框位置
    const inputRect = imageInputEle.value?.getBoundingClientRect()
    previewImageY.value = -(inputRect.height + 20);
    previewImage.value = evt.target.result;
  }
  reader.readAsDataURL(file);

  //重置输入框
  // event.target.value = '';
}

const clickVoice = () => {
  console.log(`clickVoice...`);
  console.log("imageInputEle.value?.files = ", imageInputEle.value?.files);

}
const clickVideo = () => {
  console.log(`clickVideo...`);

}


const getReceiver = (): string => {
  console.log("props.chatting = ", props.chatting)
  if (props.chatting.isGroup) {
    return props.chatting.relId;
  } else {
    return props.chatting.peerUserId;
  }
}

async function sendMessage(content: string, type: Msg_Type, receiver: string): Promise<any> {
  console.debug("do sendMessage... receiver=" + receiver);

  const isGroup = props.chatting.isGroup;
  const isUrlRef = type !== Msg_Type.TEXT && type !== Msg_Type.VOICE;

  let chatData: any = {
    message: {
      isGroup: isGroup,
      receiver: String(receiver),
      content: String(content),
      urlRef: isUrlRef,
      type: type, //消息类型：0文本、1图片、2视频、3语音、4文件
      localId: Date.now(),
    }
  }

  //补充属性并显示到UI中
  chatData.message.chatId = String(props.chatting.relId);
  chatData.message.isSelf = true;
  chatData.message.unread = true;
  chatData.message.createTime = new Date();

  //对方聊天人的信息
  const chatter = await contactStore.getChatter(props.chatting.relId, isGroup, receiver);

  console.debug("show chatMsg ...");
  showChatMsg(chatData.message, chatter, chatStore).then();

  //调用WS发送消息
  chatWS?.send(chatData);
  return true;
}


/**
 * 去查询历史聊天消息：
 * 触发场景：1、滚动条触发；2、进入面板时，chatting的messages为空时
 * @param relId
 * @param isGroup
 * @param msgId
 */
async function requestMessages() {
  const user = props.chatting.user;
  const relId = props.chatting.relId;
  const isGroup = props.chatting.isGroup;
  const msgId = props.chatting.messages[0]?.id;

  //对方聊天人的信息
  const chatter = await contactStore.getChatter(relId, isGroup, props.chatting.peerUserId);

  // console.log(`requestMessages...  relId =${relId}, msgId = ${msgId}`);
  const resp = await UserApi.findMessages(relId, isGroup, msgId);
  const persistedMessages = resp.data;

  if (persistedMessages && persistedMessages.length > 0) {
    persistedMessages.forEach(e => {
      e.createTime = new Date(e.createTime);
      e.isSelf = (e.sender === user.uid);

      setOwnerField(e, props.chatting, chatter);

    })
    props.chatting.messages.unshift(...persistedMessages);
  }
  // console.debug("setOwner persistedMessages = ", persistedMessages);
}

/* 发送消息的快捷键设置 */
onMounted(() => {
  window.addEventListener('keydown', EnterKeydown, true);
  scrollToBottom();
});
onUnmounted(() => {
  window.removeEventListener('keydown', EnterKeydown, true);
  clearPreview();
})
const EnterKeydown = (event: KeyboardEvent) => {
  // 断言 event.target 为 HTMLElement 并进一步缩小到 HTMLInputElement 或 HTMLTextAreaElement
  const target = event.target as HTMLInputElement | HTMLTextAreaElement;

  // 只处理 input 和 textarea 元素
  if (!(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) return;

  if (event.key === 'Enter') {
    event.preventDefault(); // 所有 Enter 操作都需要阻止默认行为

    if (event.ctrlKey || event.shiftKey) {
      // 插入换行符
      const start = target.selectionStart ?? target.value.length;
      const end = target.selectionEnd ?? target.value.length;
      target.value = target.value.substring(0, start) + '\n' + target.value.substring(end);
      // 恢复光标位置
      target.setSelectionRange(start + 1, start + 1);
    } else {
      clickSend(); // 触发发送
    }
  }
};


/*滚动条相关*/
//滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    if (messagesBox.value) {
      // 强制触发重排，确保DOM更新完成
      messagesBox.value.offsetHeight;
      messagesBox.value.scrollTo({
        top: messagesBox.value.scrollHeight,
        behavior: 'smooth'
      });
    }
  });
};

const isLoading = ref(false); // 加载状态
let lastScrollTop = ref(0);

const handleScroll = (e) => {
  const scrollTop = e.target.scrollTop;

  if (scrollTop < 20 && lastScrollTop.value - scrollTop > 10) {
    console.log("滚动到顶部...")
    if (!isLoading.value) {
      isLoading.value = true;
      console.log("【历史消息】准备加载更多历史记录...", new Date());

      setTimeout(() => {
        isLoading.value = false;
      }, 2000)
    }
  }

  lastScrollTop.value = e.target.scrollTop; // 更新上次的值
};

watch(() => props.chatting, (value, _) => {
  clearPreview();
  if (value.messages.length == 0) {
    requestMessages().then(() => {
      scrollToBottom();
    });
  }
  scrollToBottom();
}, {immediate: true});


// 添加自定义样式: 强制预留滚动条空间
const style = document.createElement('style')
style.textContent = ` .scrollbar-gutter-keep { scrollbar-gutter: stable; } `
document.head.appendChild(style);
</script>

<style scoped>

</style>